/**
 * Copyright (c) 2010 BullionXpress.com,
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

package com.bullionxpress.server.impl;

import java.rmi.RemoteException;
import com.bullionxpress.shared.model.Account;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
import com.bullionxpress.shared.service.AccountDatabase;
import com.bullionxpress.shared.service.AccountNotFoundException;
import com.bullionxpress.shared.service.DuplicateAccountIDException;
import com.bullionxpress.shared.service.InvalidAccountIDFormatException;
import com.bullionxpress.shared.util.Log;
import com.bullionxpress.shared.util.Utility;


public class AccountRegistrar extends java.rmi.server.UnicastRemoteObject implements AccountDatabase {
    Connection conn = null;
    Statement statement = null;
    public AccountRegistrar() throws RemoteException {
        //What should go in the constructor?
        connect();
    }

    public void connect() {
        try {
            conn = DatabaseManager.getConnection();

            try {
                statement = conn.createStatement();
                statement.executeUpdate("CREATE TABLE IF NOT EXISTS accounts (name varchar(256), id varchar(256), balance double, initial double, owner varchar(256))");
            } catch (Exception ex) {
                System.out.println(ex);
                ex.printStackTrace();
            }
        } catch (Exception ex) {
            System.out.println(ex);
            ex.printStackTrace();
        }
    }

    public Account[] getAll() {
        try {
            String query = "SELECT * FROM accounts";
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            ResultSet result = statement.executeQuery(query);
            Vector v = new Vector();
            while (result.next()) {
                Account acct = get(result.getString("id"));
                v.addElement(acct);
            }
            Account[] accountList = new Account[v.size()];
            for (int i = 0; i < v.size(); i++) {
                accountList[i] = (Account) v.get(i);
            }
            return accountList;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public Account get(String id) throws AccountNotFoundException {

        if (id == null) {
            throw new IllegalArgumentException();
        }

        String query = "SELECT * FROM accounts WHERE id = '" + id + "'";
        ResultSet result = null;
        boolean r = false;
        try {
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            result = statement.executeQuery(query);
            r = result.next();
        } catch (Exception ex) {
        }

        if (r) {
            Account acct = new Account();
            try {
                acct.setName(result.getString("name"));
                acct.setId(result.getString("id"));
                acct.setOwner(result.getString("owner"));
                acct.deposit(result.getDouble("balance"));
                acct.setInitial(result.getDouble("initial"));

            } catch(Exception ex){
                throw new AccountNotFoundException("exception filling fields");
            }
            return acct;
        } else {
            throw new AccountNotFoundException("no results from query");
        }
    }


    public Account getAccountByOwner(String owner) throws AccountNotFoundException {

        if (owner == null) {
            throw new IllegalArgumentException();
        }

        String query = "SELECT * FROM accounts WHERE owner = '" + owner + "'";
        ResultSet result = null;
        boolean r = false;
        try {
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            result = statement.executeQuery(query);
            r = result.next();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        if (r) {
            Account acct = new Account();
            try {
                acct.setName(result.getString("name"));
                acct.setId(result.getString("id"));
                acct.setOwner(result.getString("owner"));
                acct.deposit(result.getDouble("balance"));
                acct.setInitial(result.getDouble("initial"));
            } catch(Exception ex){
                ex.printStackTrace();
                throw new AccountNotFoundException();
            }
            return acct;
        } else {
            throw new AccountNotFoundException();
        }
    }

    public void register(Account b) throws DuplicateAccountIDException, InvalidAccountIDFormatException {

        if (b == null) {
            throw new IllegalArgumentException();
        } else if( b.getOwner() == null ){
            throw new IllegalStateException("Owner of account cannot be null");
        } else if( b.getOwner().equals("")){
            throw new IllegalStateException("Owner of account cannot be ''");
        }
        
        try {
            Account a = get(b.getId());
            throw new DuplicateAccountIDException();
        } catch(AccountNotFoundException ex){
            
        }

        String query = "INSERT INTO accounts (name, id, balance, initial, owner)  VALUES ( '" + b.getName() + "', '" + b.getId() + "', " + b.getBalance() + ", " + b.getInitial() + ", '" + b.getOwner() + "')";
        int n = 0;
        try {
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            n = statement.executeUpdate(query);
        } catch (SQLException ex) {
            ex.printStackTrace();
            System.out.println(ex);
        }
        if (n != 1) {
            throw new DuplicateAccountIDException();
        }
    }

    public void delete(String id) throws AccountNotFoundException, InvalidAccountIDFormatException {

        if (id == null) {
            throw new IllegalArgumentException();
        } 
        String sql = "DELETE FROM accounts WHERE id = '" + id + "'";
        int n = 0;
        try {
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            n = statement.executeUpdate(sql);
            Log.info("DELETE:" + n);
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        if (n < 1) {
            throw new AccountNotFoundException();
        }
    }

    public int count() {
        int r = 0;
        Account[] b = getAll();
        return b.length;
    }

    public void save(Account a) throws AccountNotFoundException {
        if( a == null ){
            throw new IllegalArgumentException("Cannot save null account");
        }
        if( a.getId() == null ){
            throw new IllegalStateException("Account cannot have a null id");
        }

        Account ac = get(a.getId()) ;
        if( ac == null ){
            System.out.println("Tried to get ac and it was null");
            throw new AccountNotFoundException("Account " + a.getId() + " is not found");
        }

        String query = "UPDATE accounts SET name = '" + a.getName() + "', balance = " + a.getBalance() + ", owner = '" + a.getOwner() + "' WHERE id = '" + a.getId() + "';";
        int n = 0;
        try {
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            n = statement.executeUpdate(query);
        } catch (SQLException ex) {
            ex.printStackTrace();
            System.out.println(ex);
        }
        if (n != 1) {
            throw new IllegalStateException("It should be 1");
        }
    }

}
